package com.canbot.u05.utils;

import android.content.Context;
import android.text.TextUtils;

import com.canbot.u05.update.StringUtils;

import java.io.BufferedReader;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

public class FileUtils {

        public final static String FILE_EXTENSION_SEPARATOR = ".";

        private FileUtils() {
                throw new AssertionError();
        }

        /**
         * read file
         *
         * @param filePath
         */
        public static StringBuilder readFile(String filePath, String charsetName) {
                File file = new File(filePath);
                StringBuilder fileContent = new StringBuilder("");
                if (file == null || !file.isFile()) {
                        return null;
                }

                BufferedReader reader = null;
                try {
                        InputStreamReader is = new InputStreamReader(new FileInputStream(
                                file), charsetName);
                        reader = new BufferedReader(is);
                        String line = null;
                        while ((line = reader.readLine()) != null) {
                                if (!fileContent.toString().equals("")) {
                                        fileContent.append("\r\n");
                                }
                                fileContent.append(line);
                        }
                        return fileContent;
                }
                catch (IOException e) {
                        throw new RuntimeException("IOException occurred. ", e);
                }
                finally {
                        close(reader);
                }
        }

        /**
         * write file
         *
         * @param filePath
         * @param content
         * @param append
         */
        public static boolean writeFile(String filePath, String content,
                                        boolean append) {
                if (StringUtils.isEmpty(content)) {
                        return false;
                }

                FileWriter fileWriter = null;
                try {
                        makeDirs(filePath);
                        fileWriter = new FileWriter(filePath, append);
                        fileWriter.write(content);
                        return true;
                }
                catch (IOException e) {
                        throw new RuntimeException("IOException occurred. ", e);
                }
                finally {
                        close(fileWriter);
                }
        }

        /**
         * write file, the string will be written to the begin of the file
         *
         * @param filePath
         * @param content
         * @return
         */
        public static boolean writeFile(String filePath, String content) {
                return writeFile(filePath, content, false);
        }

        /**
         * write file, the bytes will be written to the begin of the file
         *
         * @param filePath
         * @param stream
         * @return
         * @see {@link #writeFile(String, InputStream, boolean)}
         */
        public static boolean writeFile(String filePath, InputStream stream) {
                return writeFile(filePath, stream, false);
        }

        /**
         * write file
         *
         * @param file   the file to be opened for writing.
         * @param stream the input stream
         * @param append if <code>true</code>, then bytes will be written to the end of
         *               the file rather than the beginning
         * @return return true
         * @throws RuntimeException if an error occurs while operator FileOutputStream
         */
        public static boolean writeFile(String filePath, InputStream stream,
                                        boolean append) {
                return writeFile(filePath != null ? new File(filePath) : null, stream,
                        append);
        }

        /**
         * write file, the bytes will be written to the begin of the file
         *
         * @param file
         * @param stream
         * @return
         * @see {@link #writeFile(File, InputStream, boolean)}
         */
        public static boolean writeFile(File file, InputStream stream) {
                return writeFile(file, stream, false);
        }

        /**
         * write file
         *
         * @param file   the file to be opened for writing.
         * @param stream the input stream
         * @param append if <code>true</code>, then bytes will be written to the end of
         *               the file rather than the beginning
         * @return return true
         * @throws RuntimeException if an error occurs while operator FileOutputStream
         */
        public static boolean writeFile(File file, InputStream stream,
                                        boolean append) {
                OutputStream o = null;
                try {
                        makeDirs(file.getAbsolutePath());
                        o = new FileOutputStream(file, append);
                        byte data[] = new byte[1024];
                        int length = -1;
                        while ((length = stream.read(data)) != -1) {
                                o.write(data, 0, length);
                        }
                        o.flush();
                        return true;
                }
                catch (FileNotFoundException e) {
                        throw new RuntimeException("FileNotFoundException occurred. ", e);
                }
                catch (IOException e) {
                        throw new RuntimeException("IOException occurred. ", e);
                }
                finally {
                        close(o);
                        close(stream);
                }
        }

        /**
         * move file
         *
         * @param sourceFilePath
         * @param destFilePath
         */
        public static void moveFile(String sourceFilePath, String destFilePath) {
                if (TextUtils.isEmpty(sourceFilePath)
                        || TextUtils.isEmpty(destFilePath)) {
                        throw new RuntimeException(
                                "Both sourceFilePath and destFilePath cannot be null.");
                }
                moveFile(new File(sourceFilePath), new File(destFilePath));
        }

        /**
         * move file
         *
         * @param srcFile
         * @param destFile
         */
        public static void moveFile(File srcFile, File destFile) {
                boolean rename = srcFile.renameTo(destFile);
                if (!rename) {
                        copyFile(srcFile.getAbsolutePath(), destFile.getAbsolutePath());
                        deleteFile(srcFile.getAbsolutePath());
                }
        }

        /**
         * copy file
         *
         * @param sourceFilePath
         * @param destFilePath
         * @return
         */
        public static boolean copyFile(String sourceFilePath, String destFilePath) {
                InputStream inputStream = null;
                try {
                        inputStream = new FileInputStream(sourceFilePath);
                }
                catch (FileNotFoundException e) {
                        throw new RuntimeException("FileNotFoundException occurred. ", e);
                }
                return writeFile(destFilePath, inputStream);
        }

        /**
         * @param filePath
         * @param charsetName
         */
        public static List<String> readFileToList(String filePath,
                                                  String charsetName) {
                File file = new File(filePath);
                List<String> fileContent = new ArrayList<String>();
                if (file == null || !file.isFile()) {
                        return null;
                }

                BufferedReader reader = null;
                try {
                        InputStreamReader is = new InputStreamReader(new FileInputStream(
                                file), charsetName);
                        reader = new BufferedReader(is);
                        String line = null;
                        while ((line = reader.readLine()) != null) {
                                fileContent.add(line);
                        }
                        return fileContent;
                }
                catch (IOException e) {
                        throw new RuntimeException("IOException occurred. ", e);
                }
                finally {
                        close(reader);
                }
        }

        /**
         * @param filePath
         * @return file name from path, not include suffix
         * @see
         */
        public static String getFileNameWithoutExtension(String filePath) {
                if (StringUtils.isEmpty(filePath)) {
                        return filePath;
                }

                int extenPosi = filePath.lastIndexOf(FILE_EXTENSION_SEPARATOR);
                int filePosi = filePath.lastIndexOf(File.separator);
                if (filePosi == -1) {
                        return (extenPosi == -1 ? filePath : filePath.substring(0,
                                extenPosi));
                }
                if (extenPosi == -1) {
                        return filePath.substring(filePosi + 1);
                }
                return (filePosi < extenPosi ? filePath.substring(filePosi + 1,
                        extenPosi) : filePath.substring(filePosi + 1));
        }

        /**
         * @param filePath
         * @return file name from path, include suffix
         */
        public static String getFileName(String filePath) {
                if (StringUtils.isEmpty(filePath)) {
                        return filePath;
                }

                int filePosi = filePath.lastIndexOf(File.separator);
                return (filePosi == -1) ? filePath : filePath.substring(filePosi + 1);
        }

        /**
         * @param filePath
         * @return
         */
        public static String getFolderName(String filePath) {

                if (StringUtils.isEmpty(filePath)) {
                        return filePath;
                }

                int filePosi = filePath.lastIndexOf(File.separator);
                return (filePosi == -1) ? "" : filePath.substring(0, filePosi);
        }

        /**
         * @param filePath
         * @return
         */
        public static String getFileExtension(String filePath) {
                if (StringUtils.isBlank(filePath)) {
                        return filePath;
                }

                int extenPosi = filePath.lastIndexOf(FILE_EXTENSION_SEPARATOR);
                int filePosi = filePath.lastIndexOf(File.separator);
                if (extenPosi == -1) {
                        return "";
                }
                return (filePosi >= extenPosi) ? "" : filePath.substring(extenPosi + 1);
        }

        /**
         * @param filePath
         */
        public static boolean makeDirs(String filePath) {
                String folderName = getFolderName(filePath);
                if (StringUtils.isEmpty(folderName)) {
                        return false;
                }

                File folder = new File(folderName);
                return (folder.exists() && folder.isDirectory()) ? true : folder
                        .mkdirs();
        }

        /**
         * @return
         * @see #makeDirs(String)
         */
        public static boolean makeFolders(String filePath) {
                return makeDirs(filePath);
        }

        /**
         * @param filePath
         * @return
         */
        public static boolean isFileExist(String filePath) {
                if (StringUtils.isBlank(filePath)) {
                        return false;
                }

                File file = new File(filePath);
                return (file.exists() && file.isFile());
        }

        /**
         * @param directoryPath
         * @return
         */
        public static boolean isFolderExist(String directoryPath) {
                if (StringUtils.isBlank(directoryPath)) {
                        return false;
                }

                File dire = new File(directoryPath);
                return (dire.exists() && dire.isDirectory());
        }

        /**
         * @param path
         * @return
         */
        public static boolean deleteFileOrDir(String path) {
                if (StringUtils.isBlank(path)) {
                        return true;
                }

                File file = new File(path);
                if (!file.exists()) {
                        return true;
                }
                if (file.isFile()) {
                        return file.delete();
                }
                if (!file.isDirectory()) {
                        return false;
                }
                for (File f : file.listFiles()) {
                        if (f.isFile()) {
                                f.delete();
                        }
                        else if (f.isDirectory()) {
                                deleteFileOrDir(f.getAbsolutePath());
                        }
                }
                return file.delete();
        }

        /**
         * @param path
         * @return
         */
        public static boolean deleteFile(String path) {
                if (StringUtils.isBlank(path)) {
                        return true;
                }

                File file = new File(path);
                if (!file.exists()) {
                        return true;
                }
                if (file.isFile()) {
                        return file.delete();
                }
                if (!file.isDirectory()) {
                        return false;
                }
                for (File f : file.listFiles()) {
                        if (f.isFile()) {
                                f.delete();
                        }
                        else if (f.isDirectory()) {
                                deleteFile(f.getAbsolutePath());
                        }
                }
                return file.delete();
        }

        /**
         * @param path
         * @return returns the length of this file in bytes. returns -1 if the file
         * does not exist.
         */
        public static long getFileSize(String path) {
                if (StringUtils.isBlank(path)) {
                        return -1;
                }

                File file = new File(path);
                return (file.exists() && file.isFile() ? file.length() : -1);
        }

        private static void close(Closeable closeable) {
                if (closeable != null) {
                        try {
                                closeable.close();
                        }
                        catch (IOException e) {
                                throw new RuntimeException("IOException occurred. ", e);
                        }
                }
        }


        /**
         * @param name
         * @param context
         * @return
         */
        public static List<String> readAssets(String name, Context context) {
                InputStream fis = null;
                InputStreamReader isr = null;
                List<String> list = new ArrayList<String>();
                BufferedReader br = null; // 用于包装InputStreamReader,提高处理性能。因为BufferedReader有缓冲的，而InputStreamReader没有。
                try {
                        String str = "";
                        fis = context.getAssets().open(name);
                        isr = new InputStreamReader(fis, "UTF-8");
                        br = new BufferedReader(isr);// 从字符输入流中读取文件中的内容,封装了一个new
                        while ((str = br.readLine()) != null) {
                                list.add(str);
                        }
                }
                catch (FileNotFoundException e) {
                        System.out.println("找不到指定文件");
                }
                catch (IOException e) {
                        System.out.println("读取文件失败");
                }
                finally {
                        try {
                                if (br != null) {
                                        br.close();
                                }
                                if (isr != null) {
                                        isr.close();
                                }
                                if (fis != null) {
                                        fis.close();
                                }
                                // 关闭的时候最好按照先后顺序关闭最后开的先关闭所以先关s,再关n,最后关m
                        }
                        catch (IOException e) {
                                e.printStackTrace();
                        }
                }
                return list;
        }
}
